/*
 *	ApOS (Another Project software for s3c2410)
 *	
 *	This program is free software; you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License version 2 as
 *	published by the Free Software Foundation.
 *			
 *
 */
#include "../include/kernel/console.h"
#include "../include/s3c2410/lcd.h"
#include "../include/s3c2410/s3c2410.h"
#include "../src/font_ascii8x8.src"
#include "../src/font_ascii8x10.src"

unsigned int mutex=1;

static unsigned int cur_pos_x=0;

static unsigned int cur_pos_y=0;

static unsigned int view_line_max=0;

static unsigned int view_column_max=0;

static unsigned int scr_line_max=0;

static unsigned int scr_column_max=0;

static unsigned int cur_line_count=0;

static unsigned int cur_column_count=0;

static unsigned int tap_size=0;

unsigned short 	con_bkcolor=RGB(0,0,0);

unsigned short 	con_font_color=RGB(192,192,192);

unsigned short 	con_font_bkcolor=RGB(0,0,0);//RGB(0,78,152);

unsigned char  	con_font_size_width=8;

unsigned char  	con_font_size_height=8;

void set_con_bkcolor(unsigned short _bkcolor)
{
	con_bkcolor=_bkcolor;
	clear_screen(con_bkcolor);
}

void set_con_font_color(unsigned short _font_color)
{
	con_font_color=_font_color;
}

void set_con_font_bkcolor(unsigned short _font_bkcolor)
{
	con_font_bkcolor=_font_bkcolor;
}

void set_con_font_type(unsigned char font_type)
{
	switch(font_type)
	{
		case FONT8x8:
			con_font_size_width=8;
			con_font_size_height=8;
			break;
		case FONT8x10:
			con_font_size_width=8;
			con_font_size_height=10;
			break;
	}
}

unsigned char get_con_font_size_width()
{
	return con_font_size_width; 
}

unsigned char get_con_font_size_height()
{
	return con_font_size_height; 
}

unsigned int get_cur_pos_x()
{
	return cur_pos_x;
}

unsigned int get_cur_pos_y()
{
	return cur_pos_y;
}

unsigned int get_view_line_max()
{
	return view_line_max;
}

unsigned int get_view_column_max()
{
	return view_column_max;
}

unsigned int get_scr_line_max()
{
	return scr_line_max;
}

unsigned int get_scr_column_max()
{
	return scr_column_max;
}

unsigned int get_cur_line_count()
{
	return cur_line_count;
}

unsigned int get_cur_column_count()
{
	return cur_column_count;
}

unsigned int get_tap_size()
{
	return tap_size;
}

unsigned int set_tap_size(unsigned char _size)
{
	tap_size=_size;
}

void console_init()
{
	cur_pos_x=0;
	cur_pos_y=0;
	cur_line_count=0;
	cur_column_count=0;
	set_con_font_type(FONT8x10);
	set_con_bkcolor(con_font_bkcolor);
	set_con_font_bkcolor(con_font_bkcolor);
	set_con_font_color(con_font_color);
	tap_size=8;
	view_line_max=LCD_YSIZE_TFT/con_font_size_height;
	view_column_max=LCD_XSIZE_TFT/con_font_size_width;
	scr_line_max=SCR_YSIZE_TFT/con_font_size_height;
	scr_column_max=SCR_XSIZE_TFT/con_font_size_width;
	
}
void put_char(char ch)
{
	int i,j;
	for(i=0;i<con_font_size_height;i++,cur_pos_y++)
	{
		for(j=0;j<con_font_size_width;j++,cur_pos_x++)
		{
			if(ascii_8x10[ch-32].font_pixel[i][j]&1)
			{
				set_pixel(cur_pos_x,cur_pos_y,con_font_color);
			}
		}
		cur_pos_x-=con_font_size_width;
	}
	cur_pos_x+=con_font_size_width;
	cur_pos_y-=con_font_size_height;
	cur_column_count++;

}


void scroll_down()
{
	if(cur_line_count>0)
	{
		rLCDSADDR1-=SCR_XSIZE_TFT*con_font_size_height;
		rLCDSADDR2-=SCR_XSIZE_TFT*con_font_size_height;
	}
}

void scroll_up()
{
	/*if(cur_line_count<scr_line_max)
	{
		rLCDSADDR1+=SCR_XSIZE_TFT*con_font_size_height;
		rLCDSADDR2+=SCR_XSIZE_TFT*con_font_size_height;
	}
	else*/
	{
		cur_pos_x=0;
		cur_pos_y=0;
		cur_line_count=0;
		cur_column_count=0;
		lcd_scr_init();
	}
}

void feed_line()
{
	cur_pos_x=0;
	cur_pos_y+=con_font_size_height;
	cur_column_count=0;
	cur_line_count++;
	
	if(cur_line_count==view_line_max)
	{
		scroll_up();
	}
}


void console_write(char *string)
{
	char *buf=string;
	unsigned char tap_tmp;
	
	while(*buf!='\0')
	{
		switch(*buf)
		{
			case '\n':
				feed_line();
				buf++;
				break;
			case '\r':
				feed_line();
				buf++;
				break;
			case '\t':
				tap_tmp=tap_size-cur_column_count%tap_size;
				cur_column_count+=tap_tmp;
				cur_pos_x+=con_font_size_width*tap_tmp;
				if(cur_column_count>=view_column_max)
				{
					feed_line();
				}
				buf++;
				break;
			default:
				put_char(*buf);
				buf++;
				if(cur_column_count>=view_column_max)
				{
					feed_line();
				}
				break;
		}
	}

}

void text_out(unsigned int x,unsigned y,char *string)
{
	char *buf=string;
	int i,j;
	int pos_x=x,pos_y=y;
	while(*buf!='\0')
	{
		for(i=0;i<con_font_size_height;i++,pos_y++)
		{
			for(j=0;j<con_font_size_width;j++,pos_x++)
			{
				set_pixel(pos_x,pos_y,
				ascii_8x10[*buf-32].font_pixel[i][j]&1?con_font_color:con_font_bkcolor);
			}
			pos_x-=con_font_size_width;
		}
		pos_x+=con_font_size_width;
		pos_y=y;
		buf++;
	}
}